package com.deepgames.mud.session;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;

import com.deepgames.mud.core.InternalCode;

/**
 * An input/output thread which allows messages to pass back and forth between
 * 	the user and the SessionManager.
 * 
 * @author Zack Hoffmann
 * @version 1.0
 */
public class Session extends Socket implements Runnable {

	private String playerID;
	private SessionManager manager;
	private Logger log;
	
	/**
	 * Constructor designating a session manager.
	 *
	 * @param manager		Designated session manager for this session.
	 */
	public Session(SessionManager manager) {
		this.log = Logger.getLogger(Session.class.getName());
		log.setLevel(Level.parse(System.getProperty("deepmud.log.level")));
		this.manager = manager;
	}
	
	/**
	 * Listen for incoming messages then pass them to the session manager.
	 */
	@Override
	public void run() {		
		BufferedReader in;
		String inputMsg;
	
		try {
			in = new BufferedReader(
					new InputStreamReader(this.getInputStream()));
			
			while(true) {
				inputMsg = in.readLine().trim();
				if (inputMsg != null)
					passMessageToGame(inputMsg);
			}
		} catch (IOException e) {
			log.severe("Failed to capture input stream.");
			log.severe(e.toString());
			e.printStackTrace();
		} catch (NullPointerException e) {
			log.severe("Input stream failed unexpectedly.");
			log.severe(e.toString());
			e.printStackTrace();
		}
	}
	
	/**
	 * Send a message to the player.
	 * 
	 * @param msg			The message to pass to the player.
	 * @return				Status code.  {@link InternalCode}
	 */
	public int sendMsg(String msg) {
		int status = InternalCode.FAILURE;
		
		PrintWriter out;
		
		try {
			out = new PrintWriter(
					new OutputStreamWriter(this.getOutputStream()));
			out.print(msg);
			out.flush();
			status = InternalCode.SUCCESS;
		} catch (IOException e) {
			log.severe("Failed to capture output stream.");
			log.severe(e.toString());
			e.printStackTrace();
		}
		
		return status;
	}
	
	/**
	 * Replaces the sessions current player ID with a new unique ID.
	 * 
	 * @param playerID		The new player ID for this session.
	 * @return				Status code.  {@link InternalCode}
	 */
	public int setPlayerID(String playerID) {
		int status = InternalCode.FAILURE;
		
		this.playerID = playerID;
		
		return status;
	}
	
	/**
	 * Returns the currently set player ID.
	 * 
	 * @return				The current player ID for this session.
	 */
	public String getPlayerID() {
		return this.playerID;
	}
	
	/**
	 * Internal helper to allow for a flexible SessionManager interface.  Only
	 * 	change if the session manager infrastructure changes.
	 */
	private void passMessageToGame(String msg) {
		manager.sendMsgToGame(playerID, msg);
	}

}
